
/**
 *	\file
 *	Definition of the NMN_ASSERT, NMN_VERIFY, NMN_ERROR and various specialisations.
 *	\author Sean Tromans
 */

#ifndef	NMN_ASSERT_HPP
#define	NMN_ASSERT_HPP

#include <needs_more_ninja/preprocessor/force_semicolon.hpp>
#include <needs_more_ninja/preprocessor/unused.hpp>
#include <needs_more_ninja/preprocessor/breakpoint.hpp>
#include <needs_more_ninja/template/create_string.hpp>
#include <needs_more_ninja/template/output_message.hpp>
#include <boost/preprocessor.hpp>

#ifndef	NMN_ASSERTS_ON	//	Override on/off value. 
#define	NMN_ASSERTS_ON 1
#endif

#ifndef	NMN_ASSERTS_ALL	//	Whether the non-selective asserts are on or off.
#define	NMN_ASSERTS_ALL	0
#endif

#if	NMN_ASSERTS_ON

#include <needs_more_ninja/preprocessor/assert/assert_message.hpp>

#define	NMN_PROCESS_ASSERT( expression_, message_ )					\
		for(;;)														\
		{															\
			if ( nmn::detail::assert_message(	!!(expression_),	\
												message_,			\
												__FILE__,			\
												__LINE__	) )		\
			{														\
				NMN_BREAKPOINT( );									\
			}														\
			break;													\
		}															\
		NMN_FORCE_SEMICOLON( )


#define	NMN_ASSERT_IMPL( modifier_, expression_, message_ )					\
		BOOST_PP_EXPR_IF(	modifier_,										\
							NMN_PROCESS_ASSERT( expression_, message_ ) )


#define	NMN_VERIFY_IMPL( modifier_, expression_, message_ )				\
		BOOST_PP_IF(	modifier_,										\
						NMN_PROCESS_ASSERT( expression_, message_ ),	\
						expression_	)

#else

#define	NMN_ASSERT_IMPL( modifier_, expression_, message_ )
#define	NMN_VERIFY_IMPL( modifier_, expression_, message_ )	expression_; NMN_FORCE_SEMICOLON( )

#endif

#define	NMN_S_ASSERT_MESSAGE(	modifier_, expression_, message_ )	NMN_ASSERT_IMPL(		modifier_,	expression_,	nmn::create_string( "Assertion Failed: %1%", message_ ) )
#define	NMN_S_VERIFY_MESSAGE(	modifier_, expression_, message_ )	NMN_VERIFY_IMPL(		modifier_,	expression_,	nmn::create_string( "Verification Failed: %1%", message_ ) )
#define	NMN_S_ERROR_MESSAGE(	modifier_, message_ )				NMN_S_ASSERT_MESSAGE(	modifier_,	false,			nmn::create_string( "Error: %1%", message_ ) )

#define	NMN_ASSERT_MESSAGE(	expression_, message_ )					NMN_S_ASSERT_MESSAGE(	NMN_ASSERTS_ALL, expression_, message_ )
#define	NMN_VERIFY_MESSAGE(	expression_, message_ )					NMN_S_VERIFY_MESSAGE(	NMN_ASSERTS_ALL, expression_, message_ )
#define	NMN_ERROR_MESSAGE(	message_ )								NMN_S_ERROR_MESSAGE(	NMN_ASSERTS_ALL, message_ )

#define	NMN_S_ASSERT( modifier_, expression_ )						NMN_S_ASSERT_MESSAGE(	modifier_, expression_, BOOST_PP_STRINGIZE( expression_ ) )
#define	NMN_S_VERIFY( modifier_, expression_ )						NMN_S_VERIFY_MESSAGE(	modifier_, expression_, BOOST_PP_STRINGIZE( expression_ ) )
#define	NMN_S_ERROR( modifier_ )									NMN_S_ERROR_MESSAGE(	modifier_, "Unspecified" )

#define	NMN_ASSERT( expression_ )									NMN_S_ASSERT(	NMN_ASSERTS_ALL, expression_ )
#define	NMN_VERIFY( expression_ )									NMN_S_VERIFY(	NMN_ASSERTS_ALL, expression_ )
#define	NMN_ERROR( )												NMN_S_ERROR(	NMN_ASSERTS_ALL )

#endif	//NMN_ASSERT_HPP
